package cn.chiship.sdk.pay.services.impl;

import cn.chiship.sdk.core.base.BaseResult;
import cn.chiship.sdk.core.util.PrintUtil;
import cn.chiship.sdk.core.util.StringUtil;
import cn.chiship.sdk.pay.core.common.PayConstants;
import cn.chiship.sdk.pay.core.config.WxPayV3Config;
import cn.chiship.sdk.pay.core.enums.TradeTypeEnum;
import cn.chiship.sdk.pay.core.model.PayBillDownloadModel;
import cn.chiship.sdk.pay.core.model.PayParamsModel;
import cn.chiship.sdk.pay.core.model.PayRefundModel;
import cn.chiship.sdk.pay.core.model.PayTransferModel;
import cn.chiship.sdk.pay.core.model.wx.*;
import cn.chiship.sdk.pay.core.util.PayUtil;
import cn.chiship.sdk.pay.core.util.WxPayV3Util;
import cn.chiship.sdk.pay.services.PaymentService;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * 微信支付服务实现
 *
 * @author lj
 */
public class WxPayV3ServiceImpl implements PaymentService {

    private WxPayV3Config wxPayV3Config;

    private WxPayV3Util wxPayV3Util;

    public WxPayV3ServiceImpl() {
        this.wxPayV3Config = new WxPayV3Config();
        PrintUtil.console("默认构建支付句柄", this.wxPayV3Config.getMchId() + "," + this.wxPayV3Config.getAppId());
        this.wxPayV3Util = WxPayV3Util.getInstance().config(wxPayV3Config);
    }

    public WxPayV3ServiceImpl(WxPayV3Config wxPayV3Config) {
        this.wxPayV3Config = wxPayV3Config;
        PrintUtil.console("传递对象构建支付句柄", this.wxPayV3Config.getMchId() + "," + this.wxPayV3Config.getAppId());
        this.wxPayV3Util = WxPayV3Util.getInstance().config(wxPayV3Config);
    }

    @Override
    public BaseResult doPay(PayParamsModel payParamsModel, TradeTypeEnum tradeTypeEnum) {
        PrintUtil.console("支付APPID", wxPayV3Config.getAppId());
        BaseResult baseResult;
        String orderId = payParamsModel.getOrderId();
        String orderName = payParamsModel.getOrderName();
        Double totalAmount = payParamsModel.getTotalAmount();
        String openId = payParamsModel.getOpenId();
        WxPrepay wxPrepay;
        WxPrepayAmount amount = new WxPrepayAmount(Integer.valueOf(convertMoney(totalAmount)));
        String notifyUrl = payParamsModel.getNotifyDomain()
                + PayConstants.WX_NOTIFY_SUFFIX_PAY.replace("{TRADE_TYPE}", tradeTypeEnum.getCode());
        PrintUtil.console("微信支付通知", notifyUrl);

        switch (tradeTypeEnum.getCode()) {
            case "MINI_PROGRAM":
            case "OFFICIAL_ACCOUNT":
                // 小程序支付
                // 公众号支付
                if (StringUtil.isNullOrEmpty(openId)) {
                    return BaseResult.error("正在发起" + tradeTypeEnum.getMessage() + "，缺少参数【openId】");
                }
                WxPreparPayer payer = new WxPreparPayer(openId);
                wxPrepay = new WxPrepay(wxPayV3Config.getMchId(), wxPayV3Config.getAppId(), orderId, orderName, notifyUrl,
                        amount, payer);
                wxPrepay.setAttach(orderName);
                baseResult = wxPayV3Util.doJsApiPay(wxPrepay);
                break;
            case "QR_CODE":
                // 二维码支付
                wxPrepay = new WxPrepay(wxPayV3Config.getMchId(), wxPayV3Config.getAppId(), orderId, orderName, notifyUrl,
                        amount);
                wxPrepay.setAttach(orderName);
                baseResult = wxPayV3Util.doQrCodePay(wxPrepay);
                break;
            default:
                return BaseResult.error(tradeTypeEnum.getMessage() + ":不支持此支付通道");

        }
        return baseResult;
    }

    @Override
    public BaseResult doQuery(String businessId, Boolean isOrder) {
        return wxPayV3Util.doOrderQuery(businessId, isOrder);
    }

    @Override
    public BaseResult downloadBill(PayBillDownloadModel payBillDownloadModel) {
        return wxPayV3Util.downloadBill(payBillDownloadModel);
    }

    @Override
    public BaseResult doRefund(PayRefundModel payRefundModel) {
        BaseResult baseResult = PayUtil.checkRefund(payRefundModel);
        if (!baseResult.isSuccess()) {
            return baseResult;
        }

        WxRefundAmount wxRefundAmount = new WxRefundAmount(
                Integer.valueOf(convertMoney(payRefundModel.getRefundAmount())),
                Integer.valueOf(convertMoney(payRefundModel.getTotalAmount())));
        String notifyUrl = payRefundModel.getNotifyDomain() + PayConstants.WX_NOTIFY_SUFFIX_REFUND;
        PrintUtil.console("微信退款通知", notifyUrl);

        WxRefund wxRefund = new WxRefund(payRefundModel.getRefundNo(), payRefundModel.getBusinessId(),
                payRefundModel.getRefundReason(), notifyUrl, wxRefundAmount);
        return wxPayV3Util.doRefund(wxRefund);
    }

    @Override
    public BaseResult doRefundQuery(String refundId, String orderNo) {
        return wxPayV3Util.doRefundQuery(refundId);
    }

    @Override
    public BaseResult doTransfer(PayTransferModel payTransferModel) {
        WxTransferItem wxTransferItem = new WxTransferItem(payTransferModel.getTransferNo(),
                Integer.valueOf(convertMoney(payTransferModel.getTransferAmount())),
                payTransferModel.getTransferRemark(), payTransferModel.getReceiveUserId());
        List<WxTransferItem> wxTransferItems = new ArrayList<>();
        wxTransferItems.add(wxTransferItem);
        String notifyUrl = payTransferModel.getNotifyDomain() + PayConstants.WX_NOTIFY_SUFFIX_TRANSFER;
        PrintUtil.console("微信转账通知", notifyUrl);
        WxTransfer wxTransfer = new WxTransfer(wxPayV3Config.getAppId(), payTransferModel.getTransferNo(),
                payTransferModel.getTransferName(), payTransferModel.getTransferRemark(),
                Integer.valueOf(convertMoney(payTransferModel.getTransferAmount())), 1, wxTransferItems, notifyUrl);
        return wxPayV3Util.doTransferBatch(wxTransfer);
    }

    @Override
    public BaseResult doTransferQuery(String transferNo) {
        return wxPayV3Util.doTransferQuery(transferNo);
    }

    @Override
    public BaseResult doBalanceQuery() {
        return BaseResult.error("微信暂不支持商户余额查询");
    }

    /**
     * 金额转换
     *
     * @param money 金额（元）
     * @return 金额（分）
     */
    private String convertMoney(Double money) {
        return BigDecimal.valueOf(money).multiply(new BigDecimal(100)).setScale(0).toString();
    }

}
